home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / wasm.arc / RTIME.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-02-19  |  18.5 KB  |  552 lines

  1.       TITLE  'Wolfware Sample Program', 'Resident Time Display'
  2.  
  3. ;----------------------------------------------;
  4. ;             Resident Time Display            ;
  5. ;                                              ;
  6. ; A RAM resident utility which, if active,     ;
  7. ; constantly displays the time in the the      ;
  8. ; upper right corner.  Once the utility is     ;
  9. ; installed, the time is activated or          ;
  10. ; deactivated with Alt-32 (hold down the Alt   ;
  11. ; key and type 32 on the numeric keypad, then  ;
  12. ; release the Alt key).  The program is        ;
  13. ; initially non-activated when first           ;
  14. ; installed.  Once assembled, to install, just ;
  15. ; type:                                        ;
  16. ;                                              ;
  17. ; RTIME                                        ;
  18. ;                                              ;
  19. ; The time is updated about three times a      ;
  20. ; second, in the backround of whatever program ;
  21. ; is presently being executed. The time        ;
  22. ; display overwrites whatever is on the screen ;
  23. ; at that location.  The display can only be   ;
  24. ; activated or deactivated when the foreground ;
  25. ; program does keyboard I/O via interrupt 16H. ;
  26. ; This utility uses about 1065 bytes of        ;
  27. ; memory.                                      ;
  28. ;                                              ;
  29. ; For simplicity the program assumes that      ;
  30. ; there are 65535 ticks in an hour, though     ;
  31. ; there are actually 65543.  This means that   ;
  32. ; the displayed time is 8 ticks fast for each  ;
  33. ; hour past midnight.  The most it is off      ;
  34. ; occurs just before midnight, when it is      ;
  35. ; 8 * 23 = 184 ticks, or about 10 seconds fast.;
  36. ; As result of this the time actually runs to  ;
  37. ; about 24:00:10 before switching to 00:00:00. ;
  38. ;                                              ;
  39. ; This program may not be compatible with      ;
  40. ; other RAM resident type programs.            ;
  41. ;----------------------------------------------;
  42.  
  43.            PROC      FAR
  44.            JMP       INSTALL        ;skip to installation routine
  45.  
  46. TRUE       EQU       -1             ;true flag
  47. FALSE      EQU       0              ;false flag
  48.  
  49. ;----- display location, location of first character of 8 byte string
  50.  
  51. ROW        EQU       1              ;row, 1 to 25
  52. COLUMN     EQU       73             ;column, 1 to 80
  53.  
  54. ;----- execution parameters
  55.  
  56. KEY        EQU       0020H          ;int 16H key code to activate, Alt-32
  57. ATTRIBUTE  EQU       70H            ;display attribute, reverse video
  58. COUNT_SET  EQU       6              ;wait count, updated 18.2/COUNT_SET = 3/sec
  59.  
  60. ;----- BIOS data, at segment 0
  61.  
  62. EQUIP_FLAG EQU       WORD [0410H]   ;equipment word
  63. SCREEN_COL EQU       WORD [044AH]   ;CRT columns
  64.  
  65. ;----- interrupt location, at segement 0
  66.  
  67. KEYBOARD   EQU       [58H]          ;keyboard fetch, interrupt 16
  68. TIMER_TICK EQU       [70H]          ;timer tick vector location, interrupt 1C
  69.  
  70. ;----- clock information
  71.  
  72. TIMER_LOW  EQU       WORD [046CH]   ;low word of timer, at segment 0
  73. TIMER_HIGH EQU       WORD [046EH]   ;high word of timer, at segment 0
  74.  
  75. COUNTS_SEC EQU       18             ;counts in second
  76. COUNTS_MIN EQU       1092           ;counts in minute
  77. COUNTS_HOR EQU       0FFFFH         ;counts in hour
  78.  
  79. ;----- local stack size, stack has to handle local routines and overhead
  80.  
  81. STACK      EQU       20H + 80H      ;size
  82.  
  83. ;----------------------------------------------;
  84. ;                     INT16                    ;
  85. ; Alternate interrupt 16H (keyboard I/O) to    ;
  86. ; handle normal function calls while           ;
  87. ; intercepting display activation/deactivation ;
  88. ; commands. Check for command only if read key ;
  89. ; or get keyboard status (functions 0 and 1).  ;
  90. ;----------------------------------------------;
  91.  
  92. INT16      PROC      FAR
  93.            STI                      ;interrupts on
  94.            PUSHF                    ;save entry flags
  95.  
  96. ;----- read next key
  97.  
  98.            OR        AH,AH          ;check if read key
  99.            JNZ       NONKEY         ;jump if not
  100.  
  101. I16GET     SEG       CS             ;code segment
  102.            CALL      OLD_INT16      ;keyboard interrupt
  103.            CMP       AX,KEY         ;check scan code
  104.            JE        SUBKEY         ;jump if activate key
  105.            IRET
  106.  
  107. ;----- activation key on read
  108.  
  109. SUBKEY     CALL      TOGGLE_ACT     ;toggle present setting
  110.            SUB       SP,2           ;simulate flags for interrupt call
  111.            SUB       AH,AH          ;read next key function
  112.            JMPS      I16GET         ;try again
  113.  
  114. ;----- keyboard status
  115.  
  116. NONKEY     CMP       AH,1           ;check if keyboard status
  117.            JNE       NONSTAT        ;jump if not
  118.            POPF                     ;restore entry flags
  119.  
  120.            PUSHF                    ;flags for interrupt call
  121.            SEG       CS             ;code segment
  122.            CALL      OLD_INT16      ;keyboard interrupt
  123.            PUSHF
  124.            JNZ       I16CHKSK       ;jump if key in buffer
  125.  
  126.            POPF
  127.            RET       2
  128.  
  129. I16CHKSK   CMP       AX,KEY         ;check scan code
  130.            JE        I16FACT        ;jump if activate key
  131.  
  132.            POPF
  133.            RET       2
  134.  
  135. ;----- activation key on status
  136.  
  137. I16FACT    SUB       AH,AH          ;get key function
  138.            SUB       SP,2           ;simulate flags for interrupt call
  139.            SEG       CS             ;code segment
  140.            CALL      OLD_INT16      ;keyboard interrupt, get key
  141.  
  142.            CALL      TOGGLE_ACT     ;toggle present setting
  143.  
  144.            MOV       AH,1           ;status function
  145.            JMPS      NONKEY         ;try again, flags still on stack
  146.  
  147. ;----- keyboard shift status or unknown function
  148.  
  149. NONSTAT    SEG       CS             ;code segment
  150.            CALL      OLD_INT16      ;keyboard interrupt, (flags on stack)
  151.            IRET
  152.            ENDP                     ;INT16
  153.            
  154. ;----------------------------------------------;
  155. ;                  TOGGLE_ACT                  ;
  156. ; Toggle active setting and reset screen info. ;
  157. ; Clears time display (sets to dashes).        ;
  158. ;----------------------------------------------;
  159.  
  160. TOGGLE_ACT PROC      NEAR
  161.            SEG       CS
  162.            CMP       ACTIVATED,TRUE ;check if on
  163.            JE        ACTOFF         ;jump if so, turn off
  164.  
  165. ;----- activate
  166.  
  167.            SEG       CS
  168.            MOV       ACTIVATED,TRUE ;activate
  169.            SEG       CS
  170.            MOV       COUNTER,COUNT_SET ;reset counter
  171.            JMPS      SCREENRES
  172.  
  173. ;----- deactivate
  174.  
  175. ACTOFF     SEG       CS
  176.            MOV       ACTIVATED,FALSE ;activate off
  177.  
  178. ;----- reset screen information and clear display
  179.  
  180. ;----- switch to local stack
  181.  
  182. SCREENRES  SEG       CS
  183.            MOV       STACK_SEG,SS   ;save stack segment
  184.  
  185.            SEG       CS
  186.            MOV       TEMP,CS
  187.            SEG       CS
  188.            MOV       SS,TEMP        ;new stack segment
  189.  
  190.            SEG       CS
  191.            MOV       STACK_OFF,SP   ;save stack pointer
  192.  
  193.            SEG       CS
  194.            MOV       SP,LOCAL_STK   ;new stack
  195.  
  196. ;----- save all registers
  197.            
  198.            PUSH      AX
  199.            PUSH      BX
  200.            PUSH      CX
  201.            PUSH      DX
  202.            PUSH      DI
  203.            PUSH      SI
  204.            PUSH      DS
  205.            PUSH      ES
  206.  
  207.            CLD                      ;forward direction
  208.  
  209. ;----- set screen information
  210.  
  211.            SUB       AX,AX
  212.            MOV       DS,AX          ;segement 0
  213.  
  214.            MOV       BX,SCREEN_COL  ;screen columns
  215.            MOV       AX,0B800H      ;graphics segment
  216.  
  217.            MOV       DX,EQUIP_FLAG  ;get equipment flag
  218.            AND       DX,30H         ;mask CRT bits
  219.            CMP       DX,30H         ;check if BW card
  220.            JNE       NOTBW          ;jump if not
  221.  
  222.            MOV       AX,0B000H      ;BW segement
  223.  
  224. NOTBW      MOV       DX,CS
  225.            MOV       DS,DX
  226.            MOV       ES,DX          ;set data segment registers
  227.  
  228.            MOV       SCREEN_SEG,AX  ;save segment
  229.  
  230. ;----- calculate screen offset
  231.  
  232.            MOV       AX,BX
  233.            SUB       DX,DX
  234.            MUL       AX,TIME_ROW    ;row offset
  235.            ADD       AX,TIME_COL    ;add for columns
  236.            SHL       AX             ;times two, account for attribute bytes
  237.            MOV       SCREEN_OFF,AX  ;save
  238.  
  239. ;----- clear time display (set numbers to dashes)
  240.  
  241.            MOV       AX,2D2DH       ;dashes to clear time and date
  242.  
  243.            CLI                      ;interrupts off while display
  244.            MOV       DI,OFFSET TDISPLAY ;dislay line
  245.            STOSW                    ;hours
  246.            INC       DI
  247.            STOSW                    ;minutes
  248.            INC       DI
  249.            STOSW                    ;seconds
  250.  
  251.            CALL      DISPLAY        ;display new string
  252.            STI                      ;interrupts back on
  253.  
  254. ;----- restore registers
  255.  
  256.            POP       ES
  257.            POP       DS
  258.            POP       SI
  259.            POP       DI
  260.            POP       DX
  261.            POP       CX
  262.            POP       BX
  263.            POP       AX
  264.  
  265. ;----- restore stack
  266.  
  267.            SEG       CS
  268.            MOV       SP,STACK_OFF   ;stack pointer
  269.  
  270.            SEG       CS
  271.            MOV       SS,STACK_SEG   ;stack segment
  272.            RET
  273.            ENDP                     ;TOGGLE_ACT
  274.  
  275. ;----------------------------------------------;
  276. ;                     INT1C                    ;
  277. ; Alternate interrupt 1CH (timer tick).        ;
  278. ; Executed every timer tick (about 18.2 times  ;
  279. ; a second).                                   ;
  280. ;                                              ;
  281. ; One out of COUNT_SET cycles the time is      ;
  282. ; displayed to its predetermined location, so  ;
  283. ; the time is actually updated 18.2/COUNT_SET  ;
  284. ; times per second.                            ;
  285. ;                                              ;
  286. ; Each interrupt calls the original timer tick ;
  287. ; interrupt for the benefit of any other       ;
  288. ; routines that were using it for their own    ;
  289. ; execution.                                   ;
  290. ;----------------------------------------------;
  291.  
  292. INT1C      PROC      NEAR
  293.            CLI                      ;interrupts off
  294.  
  295. ;----- check if activated
  296.  
  297.            SEG       CS
  298.            CMP       ACTIVATED,TRUE ;check if activated
  299.            JE        REDISCHK       ;jump if so
  300.  
  301. EXIT       PUSHF                    ;flags for interrupt call
  302.            SEG       CS
  303.            CALL      OLD_INT1C      ;call original interrupt
  304.            IRET
  305.  
  306. REDISCHK   SEG       CS
  307.            DEC       COUNTER        ;decrement counter
  308.            JNZ       EXIT           ;jump if not zero
  309.  
  310. ;----- redisplay time
  311.  
  312. ;----- switch to internal stack
  313.  
  314.            SEG       CS
  315.            MOV       ACTIVATED,FALSE ;deactivate
  316.  
  317.            SEG       CS
  318.            MOV       STACK_SEG,SS   ;save stack segment
  319.  
  320.            SEG       CS
  321.            MOV       TEMP,CS
  322.            SEG       CS
  323.            MOV       SS,TEMP        ;new stack segment
  324.  
  325.            SEG       CS
  326.            MOV       STACK_OFF,SP   ;save stack pointer
  327.  
  328.            SEG       CS
  329.            MOV       SP,LOCAL_STK   ;new stack
  330.  
  331. ;----- save all registers
  332.  
  333.            PUSH      AX
  334.            PUSH      BX
  335.            PUSH      CX
  336.            PUSH      DX
  337.            PUSH      DI
  338.            PUSH      SI
  339.            PUSH      DS
  340.            PUSH      ES
  341.  
  342.            CLD                      ;forward direction
  343.  
  344. ;----- get time
  345.  
  346.            SUB       AX,AX
  347.            MOV       DS,AX          ;segment 0
  348.  
  349.            MOV       DX,[TIMER_HIGH] ;timer high
  350.            MOV       AX,[TIMER_LOW]  ;timer low
  351.  
  352. ;----- set time
  353.  
  354.            MOV       BX,CS
  355.            MOV       DS,BX
  356.            MOV       ES,BX          ;set segment registers
  357.  
  358.            MOV       COUNTER,COUNT_SET ;reset counter
  359.  
  360.            MOV       DI,OFFSET TDISPLAY ;start of time display string
  361.  
  362.            MOV       BX,COUNTS_HOR  ;counts/hour
  363.            DIV       AX,BX          ;divide
  364.            CALL      NUMBER_CON     ;convert to ASCII and store
  365.            INC       DI             ;skip colon
  366.  
  367.            MOV       AX,DX          ;remainder is new dividend
  368.            SUB       DX,DX
  369.            MOV       BX,COUNTS_MIN  ;counts/minute
  370.            DIV       AX,BX          ;divide
  371.            CALL      NUMBER_CON     ;convert to ASCII and store
  372.            INC       DI             ;skip colon
  373.  
  374.            MOV       AX,DX          ;remainder is new dividend
  375.            SUB       DX,DX
  376.            MOV       BX,COUNTS_SEC  ;counts/second
  377.            DIV       AX,BX          ;divide
  378.            CALL      NUMBER_CON     ;convert to ASCII and store
  379.  
  380.            CALL      DISPLAY        ;display string to screen
  381.  
  382. ;----- restore registers
  383.  
  384.            POP       ES
  385.            POP       DS
  386.            POP       SI
  387.            POP       DI
  388.            POP       DX
  389.            POP       CX
  390.            POP       BX
  391.            POP       AX
  392.  
  393. ;----- restore stack
  394.  
  395.            SEG       CS
  396.            MOV       SP,STACK_OFF   ;restore stack pointer
  397.  
  398.            SEG       CS
  399.            MOV       SS,STACK_SEG   ;restore stack segment
  400.  
  401.            SEG       CS
  402.            MOV       ACTIVATED,TRUE ;reactivate
  403.            JMP       EXIT           ;exit routine
  404.            ENDP                     ;INT1C
  405.  
  406. ;----------------------------------------------;
  407. ;                  NUMBER_CON                  ;
  408. ; Convert number in AL to two digit ASCII      ;
  409. ; string and store result to DI. Number must   ;
  410. ; be in range 0 to 99.  DI returns pointing to ;
  411. ; byte after new string.                       ;
  412. ;----------------------------------------------;
  413.  
  414. NUMBER_CON PROC      NEAR
  415.            SHL       AL
  416.            SUB       AH,AH          ;AX gets relative offset
  417.            ADD       AX,OFFSET NUMBERS ;absolute offset
  418.            MOV       SI,AX
  419.            MOVSW                    ;move word (two byte digits)
  420.            RET
  421.  
  422. ;----- data, 00 to 99
  423.  
  424. NUMBERS    LABEL     BYTE
  425.            DB        '00010203040506070809'
  426.            DB        '10111213141516171819'
  427.            DB        '20212223242526272829'
  428.            DB        '30313233343536373839'
  429.            DB        '40414243444546474849'
  430.            DB        '50515253545556575859'
  431.            DB        '60616263646566676869'
  432.            DB        '70717273747576777879'
  433.            DB        '80818283848586878889'
  434.            DB        '90919293949596979899'
  435.            ENDP                     ;NUMBER_CON
  436.  
  437. ;----------------------------------------------;
  438. ;                    DISPLAY                   ;
  439. ; Display the time string to the screen by     ;
  440. ; writing it directly to the screen buffer.    ;
  441. ;----------------------------------------------;
  442.  
  443. DISPLAY    PROC      NEAR
  444.            MOV       AH,ATTRIBUTE   ;display attribute
  445.            MOV       CX,OFFSET TDISPLAY_END - OFFSET TDISPLAY ;length
  446.            MOV       DI,SCREEN_OFF  ;offset into screen
  447.            MOV       SI,OFFSET TDISPLAY ;start of time string
  448.            MOV       ES,SCREEN_SEG  ;segment of screen
  449.  
  450. ;----- move string to screen buffer
  451.  
  452. DISLOOP    LODSB                    ;load character
  453.            STOSW                    ;store character and attribute
  454.            LOOP      DISLOOP        ;loop CX times
  455.            RET
  456.            ENDP                     ;DISPLAY
  457.  
  458. ;----------------------------------------------;
  459. ;                     Data                     ;
  460. ;----------------------------------------------;
  461.  
  462. ACTIVATED  DB        FALSE          ;activation status, initially off
  463. COUNTER    DB        ?              ;execution counter, set when activated
  464.  
  465. TIME_ROW   DW        ROW - 1        ;display row
  466. TIME_COL   DW        COLUMN - 1     ;display column
  467.  
  468. STACK_OFF  DW        ?              ;storage for stack offset
  469. STACK_SEG  DW        ?              ;storage for stack segment
  470. LOCAL_STK  DW        OFFSET END + STACK ;local stack top
  471.  
  472. SCREEN_OFF DW        ?              ;screen offset
  473. SCREEN_SEG DW        ?              ;screen segment
  474.  
  475. TEMP       DW        ?              ;temporary storage
  476.  
  477. ;----- display string
  478.  
  479. TDISPLAY   LABEL     BYTE           ;start of string
  480.            DB        '--:--:--'
  481. TDISPLAY_END LABEL     BYTE         ;end of string (to calculate length)
  482.  
  483. ;----- original interrupts
  484.  
  485. OLD_INT16  LABEL     DWORD
  486.            DW        ?              ;offset
  487.            DW        ?              ;segment
  488.  
  489. OLD_INT1C  LABEL     DWORD
  490.            DW        ?              ;offset
  491.            DW        ?              ;segment
  492.  
  493. END        LABEL     BYTE           ;end of code and data, start of stack space
  494.  
  495. ;----------------------------------------------;
  496. ;                   INSTALL                    ;
  497. ; Install the alternate interrupts.            ;
  498. ;----------------------------------------------;
  499.  
  500. INSTALL    PROC      NEAR
  501.            CLI                      ;disable interrupts
  502.  
  503. ;----- install new interrupt vectors
  504.  
  505.            MOV       AX,OFFSET INT16 ;keyboard offset
  506.            MOV       BX,CS           ;present segement
  507.            MOV       CX,OFFSET INT1C ;timer offset
  508.            MOV       DX,CS           ;present segement
  509.  
  510.            PUSH      DS
  511.            SUB       BP,BP
  512.            MOV       DS,BP          ;segment 0
  513.  
  514.            XCHG      AX,WORD KEYBOARD
  515.            XCHG      BX,WORD KEYBOARD+2   ;install int 16
  516.            XCHG      CX,WORD TIMER_TICK
  517.            XCHG      DX,WORD TIMER_TICK+2 ;install int 1C
  518.            POP       DS
  519.  
  520. ;----- save the old ones
  521.  
  522.            MOV       WORD OLD_INT16,AX
  523.            MOV       WORD OLD_INT16+2,BX ;save int 16
  524.            MOV       WORD OLD_INT1C,CX
  525.            MOV       WORD OLD_INT1C+2,DX ;save int 1C
  526.  
  527.            STI                      ;enable interrupts
  528.  
  529. ;----- display message
  530.  
  531.            MOV       DX,OFFSET INSTALLM ;message location
  532.            MOV       AH,9           ;print string function
  533.            INT       21H            ;execute
  534.  
  535. ;----- finish up
  536.  
  537.            MOV       DX,LOCAL_STK   ;end of interrupt, top of local stack
  538.            INT       27H            ;terminate but stay resident
  539.  
  540. ;----- message
  541.  
  542. INSTALLM   DB  10                                                        
  543.            DB  '/-------------------------------------------\',13,10
  544.            DB  '|  Resident time display utility installed  |',13,10
  545.            DB  '|-------------------------------------------|',13,10
  546.            DB  '|    press ALT-32 to activate/deactivate    |',13,10
  547.            DB  '\-------------------------------------------/',13,10,'$'
  548.            ENDP                                 ;INSTALL
  549.  
  550.            ENDP
  551. 
  552.